package com.zg.datapush.service;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zg.common.core.R;
import com.zg.datapush.constant.DataPushConstants;
import com.zg.common.core.dao.datapush.dao.DpPushTaskDao;
import com.zg.common.core.dao.datapush.entity.DpPushTask;
import com.zg.datapush.vo.DpPushTaskVo;
import com.zg.datapush.req.DpPushTaskAddReq;
import com.zg.datapush.req.DpPushTaskPageReq;
import com.zg.datapush.req.DpPushTaskUpdateReq;
import com.zg.datapush.util.CronUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.stream.Collectors;

/**
 * 推送任务服务
 * @author zg
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class DpPushTaskService {

    private final DpPushTaskDao pushTaskDao;
    private final PushService pushService;
    private final TaskScheduleService taskScheduleService;
    private final DatasourceQueryService datasourceQueryService;

    /**
     * 分页查询推送任务
     */
    public IPage<DpPushTaskVo> page(Page<DpPushTask> page, DpPushTaskPageReq query) {
        LambdaQueryWrapper<DpPushTask> wrapper = new LambdaQueryWrapper<>();

        if (query.getTaskName() != null) {
            wrapper.like(DpPushTask::getTaskName, query.getTaskName());
        }
        if (query.getTargetType() != null) {
            wrapper.eq(DpPushTask::getTargetType, query.getTargetType());
        }
        if (query.getStatus() != null) {
            wrapper.eq(DpPushTask::getStatus, query.getStatus());
        }

        IPage<DpPushTask> entityPage = pushTaskDao.page(page, wrapper);

        // 转换为VO
        IPage<DpPushTaskVo> voPage = new Page<>();
        BeanUtil.copyProperties(entityPage, voPage);
        voPage.setRecords(entityPage.getRecords().stream()
            .map(entity -> {
                DpPushTaskVo vo = new DpPushTaskVo();
                BeanUtil.copyProperties(entity, vo);
                return vo;
            })
            .collect(Collectors.toList()));

        return voPage;
    }

    /**
     * 新增推送任务
     */
    public R<DpPushTask> add(DpPushTaskAddReq req) {
        // 验证任务配置
        R<Void> validateResult = validateTaskConfig(req);
        if (!validateResult.isOk()) {
            return R.error(validateResult.getMessage());
        }

        // 检查任务名称是否重复
        boolean exists = pushTaskDao.exists(
            new LambdaQueryWrapper<DpPushTask>()
                .eq(DpPushTask::getTaskName, req.getTaskName())
        );
        if (exists) {
            return R.error("任务名称已存在");
        }

        DpPushTask entity = new DpPushTask();
        BeanUtil.copyProperties(req, entity);

        pushTaskDao.save(entity);
        return R.success(entity);
    }

    /**
     * 更新推送任务
     */
    public R<DpPushTask> update(DpPushTaskUpdateReq req) {
        DpPushTask entity = pushTaskDao.getById(req.getId());
        if (entity == null) {
            return R.error("推送任务不存在");
        }

        // 检查任务名称是否重复
        boolean exists = pushTaskDao.exists(
            new LambdaQueryWrapper<DpPushTask>()
                .eq(DpPushTask::getTaskName, req.getTaskName())
                .ne(DpPushTask::getId, req.getId())
        );
        if (exists) {
            return R.error("任务名称已存在");
        }

        BeanUtil.copyProperties(req, entity);
        pushTaskDao.updateById(entity);
        return R.success(entity);
    }

    /**
     * 删除推送任务
     */
    public R<Void> delete(List<Long> ids) {
        pushTaskDao.removeBatchByIds(ids);
        return R.success();
    }

    /**
     * 启用推送任务
     */
    public R<Void> enable(Long id) {
        DpPushTask task = pushTaskDao.getById(id);
        if (task == null) {
            return R.error("推送任务不存在");
        }

        task.setStatus(DataPushConstants.TASK_STATUS_ENABLED);
        pushTaskDao.updateById(task);

        // 如果是定时调度，启动调度
        if (DataPushConstants.SCHEDULE_TYPE_CRON.equals(task.getScheduleType())) {
            taskScheduleService.startTaskSchedule(id);
        }

        return R.success();
    }

    /**
     * 禁用推送任务
     */
    public R<Void> disable(Long id) {
        DpPushTask task = pushTaskDao.getById(id);
        if (task == null) {
            return R.error("推送任务不存在");
        }

        task.setStatus(DataPushConstants.TASK_STATUS_DISABLED);
        pushTaskDao.updateById(task);

        // 停止调度
        taskScheduleService.stopTaskSchedule(id);

        return R.success();
    }

    /**
     * 手动执行推送任务
     */
    public R<Void> execute(Long id) {
        DpPushTask task = pushTaskDao.getById(id);
        if (task == null) {
            return R.error("推送任务不存在");
        }

        try {
            pushService.executePushTask(id);
            return R.success();
        } catch (Exception e) {
            log.error("手动执行推送任务失败", e);
            return R.error("执行失败: " + e.getMessage());
        }
    }

    /**
     * 启动任务调度
     */
    public R<Void> startSchedule(Long id) {
        DpPushTask task = pushTaskDao.getById(id);
        if (task == null) {
            return R.error("推送任务不存在");
        }

        if (!DataPushConstants.SCHEDULE_TYPE_CRON.equals(task.getScheduleType())) {
            return R.error("只有定时任务才能启动调度");
        }

        taskScheduleService.startTaskSchedule(id);
        return R.success();
    }

    /**
     * 停止任务调度
     */
    public R<Void> stopSchedule(Long id) {
        DpPushTask task = pushTaskDao.getById(id);
        if (task == null) {
            return R.error("推送任务不存在");
        }

        taskScheduleService.stopTaskSchedule(id);
        return R.success();
    }

    /**
     * 验证任务配置
     */
    private R<Void> validateTaskConfig(DpPushTaskAddReq req) {
        // 验证基本信息
        if (StrUtil.isBlank(req.getTaskName())) {
            return R.error("任务名称不能为空");
        }

        if (StrUtil.isBlank(req.getSourceDatasourceCode())) {
            return R.error("源数据源不能为空");
        }

        if (StrUtil.isBlank(req.getSourceTableName())) {
            return R.error("源表名不能为空");
        }

        if (StrUtil.isBlank(req.getTargetType())) {
            return R.error("目标类型不能为空");
        }

        // 验证数据源是否存在
        if (datasourceQueryService.getByCode(req.getSourceDatasourceCode()) == null) {
            return R.error("源数据源不存在: " + req.getSourceDatasourceCode());
        }

        // 验证目标配置
        if (DataPushConstants.TARGET_TYPE_DATABASE.equals(req.getTargetType())) {
            if (StrUtil.isBlank(req.getTargetDatasourceCode())) {
                return R.error("目标数据源不能为空");
            }
            if (StrUtil.isBlank(req.getTargetTableName())) {
                return R.error("目标表名不能为空");
            }
            if (datasourceQueryService.getByCode(req.getTargetDatasourceCode()) == null) {
                return R.error("目标数据源不存在: " + req.getTargetDatasourceCode());
            }
        }

        // 验证调度配置
        if (DataPushConstants.SCHEDULE_TYPE_CRON.equals(req.getScheduleType())) {
            if (StrUtil.isBlank(req.getCronExpression())) {
                return R.error("Cron表达式不能为空");
            }
            if (!CronUtil.isValidCron(req.getCronExpression())) {
                return R.error("Cron表达式格式不正确");
            }
        }

        // 验证增量推送配置
        if (DataPushConstants.PUSH_MODE_INCREMENT.equals(req.getPushMode())) {
            if (StrUtil.isBlank(req.getIncrementField())) {
                return R.error("增量字段不能为空");
            }
        }

        return R.success();
    }
}
